/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package airAgent.group5;

//import airAgent.group5.ontology.ontology.AirAgentOntology;
//import airAgent.group5.ontology.ontology.EndOfSimulation;
//import airAgent.group5.ontology.ontology.InformDate;
//import airAgent.group5.ontology.ontology.StartSimulation;
import airAgent.group5.ontology.ontology.*;
import jade.content.lang.Codec;
import jade.content.lang.Codec.CodecException;
import jade.content.lang.sl.SLCodec;
import jade.content.onto.Ontology;
import jade.content.onto.OntologyException;
import jade.content.onto.basic.Action;
import jade.core.AID;
import jade.core.Agent;
import jade.core.behaviours.CyclicBehaviour;
import jade.core.behaviours.OneShotBehaviour;
import jade.core.behaviours.SimpleBehaviour;
import jade.core.behaviours.TickerBehaviour;
import jade.core.behaviours.WakerBehaviour;
import jade.domain.DFService;
import jade.domain.FIPAAgentManagement.DFAgentDescription;
import jade.domain.FIPAAgentManagement.ServiceDescription;
import jade.domain.FIPAException;
import jade.lang.acl.ACLMessage;
import jade.lang.acl.MessageTemplate;
import java.io.*;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 *
 * @author hector
 */
public class Timer extends Agent {

    airAgent.group5.ontology.ontology.Airline ontoAirline = new airAgent.group5.ontology.ontology.Airline();
    private Codec codec = new SLCodec();
    private Ontology ontology = AirAgentOntology.getInstance();
    private ArrayList timeSusbcribers = null;
    private int airlinesCount = -1; // TODO read from configuration
    private int currentDay = 0;
    private long timeout = -1; // TODO read from configuration
    private int maxDate = 0;
//    private String configFileDir = "/home/hector/NetBeansProjects/airline/trunk/src/airAgent/group5";

//    private String configFileDir = "/home/alex/workspace/absd-group5/bin/airAgent/group5";

    private class ResponseSubscribeTimerBehaviour extends CyclicBehaviour {

        /*
        private Agent agent;

        public ResponseSubscribeTimerBehaviour(Agent agent) {
            this.agent = agent;
        }
        */

        @Override
        public void action() {
            ACLMessage msg = receive(MessageTemplate.MatchProtocol(AirAgentOntology.SUBSCRIBETIMER));

            if (msg != null) {
                ACLMessage reply = msg.createReply();
                if (msg.getPerformative() == ACLMessage.SUBSCRIBE) {
                    reply.setPerformative(ACLMessage.AGREE);
                    reply.setProtocol(AirAgentOntology.SUBSCRIBETIMER);
                    timeSusbcribers.add(msg.getSender());
                    send(reply);
                    /*
                    if (timeSusbcribers.size() == airlinesCount) {
                        addBehaviour(new InformStartSimulationBehaviour(agent));
                    }

                     */
                } else {
                    // TODO: ask it again?
                    reply.setPerformative(ACLMessage.NOT_UNDERSTOOD);
                }
            } else {
                block();
            }
        }
    }

    //private class InformStartSimulationBehaviour extends OneShotBehaviour {
        private class InformStartSimulationBehaviour extends WakerBehaviour {

        private Agent agent;

        public InformStartSimulationBehaviour(Agent agent,long timeout) {
            super(agent,timeout);
            this.agent = agent;

        }

        @Override
        //public void action() {
        public void onWake() {
            ACLMessage msg = null;
            for (int i = 0; i < timeSusbcribers.size(); i++) {
                AID subsRef = (AID) timeSusbcribers.get(i);
                msg = new ACLMessage(ACLMessage.INFORM);
                msg.addReceiver(subsRef);
                msg.setProtocol(AirAgentOntology.STARTSIMULATION);
                msg.setLanguage(codec.getName());
                msg.setOntology(ontology.getName());
                StartSimulation startSimulation = new StartSimulation();
                Action startSimuAction = new Action(subsRef, startSimulation);
                try {
                    // The ContentManager transforms the java objects into strings
                    getContentManager().fillContent(msg, startSimuAction);
                    send(msg);
                   // System.out.println(getLocalName() + ": informing with the start of simulation");
                } catch (CodecException ce) {
                    ce.printStackTrace();
                } catch (OntologyException oe) {
                    oe.printStackTrace();
                }

            }
            addBehaviour(new InformDateBehaviour(agent, timeout));
        }
    }

    private class EndOfSimulationBehaviour extends OneShotBehaviour {

        @Override
        public void action() {
            ACLMessage msg = null;
            for (int i = 0; i < timeSusbcribers.size(); i++) {
                AID subsRef = (AID) timeSusbcribers.get(i);
                msg = new ACLMessage(ACLMessage.INFORM);
                msg.addReceiver(subsRef);
                msg.setProtocol(AirAgentOntology.ENDOFSIMULATION);
                msg.setLanguage(codec.getName());
                msg.setOntology(ontology.getName());
                EndOfSimulation endSimulation = new EndOfSimulation();
                Action endSimuAction = new Action(subsRef, endSimulation);
                try {
                    // The ContentManager transforms the java objects into strings
                    getContentManager().fillContent(msg, endSimuAction);
                    send(msg);
                 //   System.out.println(getLocalName() + ": informing with the end of simulation");
                } catch (CodecException ce) {
                    ce.printStackTrace();
                } catch (OntologyException oe) {
                    oe.printStackTrace();
                }
               
            }
            System.out.println("END OF THE SIMULATION");
            doDelete();
        }
    }

    //private class InformDateBehaviour extends CyclicBehaviour {
    //TODO change for cyclic
    private class InformDateBehaviour extends TickerBehaviour {

        private boolean end;

        public InformDateBehaviour(Agent ag, long timeout) {
            super(ag, timeout);
        }

        @Override
        public void onTick() {
            ACLMessage msg = null;
            currentDay++;
            System.out.println("DAY " +currentDay+" OF 1");
            for (int i = 0; i < timeSusbcribers.size(); i++) {
                if (currentDay == (maxDate+1)) {
                    addBehaviour(new EndOfSimulationBehaviour());
                } else {
                    AID subsRef = (AID) timeSusbcribers.get(i);
                    msg = new ACLMessage(ACLMessage.INFORM);
                    msg.addReceiver(subsRef);
                    InformDate inf = new InformDate();
                    inf.setDate(currentDay); //TODO: just just add currentDay
                    msg.setProtocol(AirAgentOntology.INFORMDATE);
                    msg.setLanguage(codec.getName());
                    msg.setOntology(ontology.getName());
                    Action infDateAction = new Action(subsRef, inf);
                    try {
                        // The ContentManager transforms the java objects into strings
                        getContentManager().fillContent(msg, infDateAction);
                        send(msg);
                        end = true;
                      //  System.out.println(getLocalName() + ": informing with the date");
                    } catch (CodecException ce) {
                        ce.printStackTrace();
                    } catch (OntologyException oe) {
                        oe.printStackTrace();
                    }
                }

            }
        }
    }

    private void setAirlinesCount(int count) {
        airlinesCount = count;
    }

    private void setTimeout(long tout) {
        timeout = tout;
    }
    private void setMaxDate(int maxDate) {
        this.maxDate = maxDate;
    }

    private boolean readConfigFile(){


        try {
            File file =   new File("settings.properties");
            Scanner scanner = new Scanner(file);
            while (scanner.hasNextLine()) {
                String configFileLine = scanner.nextLine();
                try{
                    String [] variableValue = configFileLine.split("=");
                    if (variableValue[0].equals("timeout"))
                        setTimeout(Long.parseLong(variableValue[1]));
                    else if (variableValue[0].equals("airlineCount"))
                    {
                        setAirlinesCount(Integer.parseInt(variableValue[1]));
                    }
                    else if (variableValue[0].equals("simulationDays"))
                    {
                        setMaxDate(Integer.parseInt(variableValue[1]));
                    }
                }catch(Exception e)
                {
                    System.out.println(getLocalName()+":Cannot parse line in config file: "+configFileLine);
                    e.printStackTrace();
                }

            }
            scanner.close();
            
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        }
             
        if ((airlinesCount != -1) && (timeout != -1))
            return true;
        return false;
    }

    @Override
    protected void setup() {
        timeSusbcribers = new ArrayList();
        if (!readConfigFile())
            doDelete();
       // System.out.println(getLocalName() + ": Timer created");
        getContentManager().registerLanguage(codec);
        getContentManager().registerOntology(ontology);


        try {
            // Creates its own description
            DFAgentDescription dfd = new DFAgentDescription();
            ServiceDescription sd = new ServiceDescription();
            sd.setName(this.getName());
            sd.setType(AirAgentOntology.TIMER);
            dfd.addServices(sd);
            // Registers its description in the DF
            DFService.register(this, dfd);
         //   System.out.println(getLocalName() + ": registered in the DF");

        } catch (FIPAException e) {
            e.printStackTrace();
        }
        addBehaviour(new ResponseSubscribeTimerBehaviour());
        addBehaviour(new InformStartSimulationBehaviour(this,30000));
        //addBehaviour(new ResponseSubscribeTimerBehaviour(this));

    }
}
